package net.sf.calibur.ai.pathfinder;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Arrays;

public class TiledMap {
	private final static int PATH = 0;
	private final static int BARRIER = 2;
	
	private int horizontalTilesNum, verticalTilesNum;
	private int[] mapData;
	
	public TiledMap(int hNum, int vNum) {
		this.horizontalTilesNum = hNum;
		this.verticalTilesNum = vNum;
		this.mapData = new int[vNum * hNum];
	}
	
	public void clear() {
		Arrays.fill(mapData, PATH);
	}

	public void loadData(int[][] data, int barrierVal, int clearVal) {
		horizontalTilesNum = data[0].length;
		verticalTilesNum = data.length;
		if (horizontalTilesNum * verticalTilesNum > mapData.length) {
			mapData = new int[horizontalTilesNum * verticalTilesNum];
		}

		clear();
		for (int i = 0; i < verticalTilesNum; i++) {
			for (int j = 0; j < horizontalTilesNum; j++) {
				if (data[i][j] == barrierVal) {
					set(j, i, BARRIER);
				} else {
					set(j, i, PATH);
				}
			}
		}
	}

	public int getHorizontalTilesNum() {
		return horizontalTilesNum;
	}

	public int getVerticalTilesNum() {
		return verticalTilesNum;
	}
	
	public int get(int x, int y) {
		return mapData[y * horizontalTilesNum + x];
	}
	
	public void set(int x, int y, int v) {
		mapData[y * horizontalTilesNum + x] = v;
	}
	
	public void setToBarrierNode(int x, int y) {
		set(x, y, BARRIER);
	}
	
	public void setToPathNode(int x, int y) {
		set(x, y, PATH);
	}
	
	public boolean isBarrier(int x, int y) {
		return get(x, y) == BARRIER;
	}
	
	public void toggleBarrier(int x, int y) {
		set(x, y, isBarrier(x, y) ? PATH : BARRIER);
	}
	
//	public int[][] getData() {
//		int[][] data = new int[verticalTilesNum][horizontalTilesNum];
//		for (int y = 0; y < verticalTilesNum; ++y) {
//			for (int x = 0; x < horizontalTilesNum; ++x) {
//				data[y][x] = get(x, y);
//			}
//		}
//		
//		return data;
//	}
	
	public void writeTo(OutputStream ostream) throws IOException {
		PrintStream ps = new PrintStream(ostream);
		ps.println(String.format("%d %d", horizontalTilesNum, verticalTilesNum));
		for (int y = 0; y < verticalTilesNum; ++y) {
			for (int x = 0; x < horizontalTilesNum; ++x) {
				if (isBarrier(x, y)) {
					ps.println(String.format("%d %d", x, y));
				}
			}
		}
	}
	
	public void readFrom(InputStream istream) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(istream));
		String line;
		boolean first = true;
		int x, y;
		String[] elem;
		
		while ((line = reader.readLine()) != null) {
			line = line.trim();
			if (line.length() == 0) {
				continue;
			} else if (line.startsWith("#")) {
				continue;
			}
			
			elem = line.split("[ |\\t]+");
			x = Integer.parseInt(elem[0]);
			y = Integer.parseInt(elem[1]);
			
			if (first) {
				horizontalTilesNum = x;
				verticalTilesNum = y;
				if (mapData.length < x * y) {
					mapData = new int[x * y];
				}
				first = false;
				clear();
			} else {
				setToBarrierNode(x, y);
			}
		}
	}
}
